#coding=utf8
try:
    import queue
except:
    import Queue as queue
import threading
from core.filter.ioFilter import FilterChain
from ws_setting import logger, CUSTOM_OBJ_SESSION_ID_NAME
from core.session import Session

class SocketTypeError(Exception):
    pass


class DefaultContainer:
    """
        default application container
    """
    ws_application = {} #store globle variables
    message_sender_queue = queue.Queue()

    def __init__(self, config=None):
        if config:#just for test
            self.config = config

    def url_definition(self, context):
        """
              获取URL配置定义
              返回：dict URL映射规则
        """
        if self.config:
            for path_url, conf in self.config.urls:
                if path_url == context:
                    return lambda key: key in conf and conf.get(key) or ""
        else:
            logger.warning("no module found")

    def get_sessions(self, key=None):
        if key:
            return self._sessionStorage.get(key, None)
        else:
            return self._sessionStorage

    def initialization(self):
        """
            init required module
        """
        self._sessionStorage = SessionStorage()

        sender = MessageSender(self.message_sender_queue)
        sender.daemon = True
        sender.name = "message sender thread"
        sender.start()

    def get_filterChain(self):
        filterChain = FilterChain()
        filterChain.initialization(self.config)
        return filterChain

    def remove_session(self, session):
        self._sessionStorage.remove(session)
        logger.debug("session {} removed and {} alive sessions ".format(session, len(self._sessionStorage)))

    def add_session(self, session):
        self._sessionStorage.add(session)
        logger.debug("new session added and {} alive sessions ".format(len(self._sessionStorage)))

    def clean(self):
        for session in self._sessionStorage.values():
            print "close " + getattr(session, CUSTOM_OBJ_SESSION_ID_NAME)
            session.close_session()
        #map(lambda sess: sess.handle.close_socket(), self._sessionStorage.values())

def validateParm(function):
    def wrapper(*args):
        if isinstance(args[1], Session) and getattr(args[1], CUSTOM_OBJ_SESSION_ID_NAME) is not None:
            return function(*args)
        else:
            raise SocketTypeError("error session object, or session not initialization")

    return wrapper


class SessionStorage(dict):
    @validateParm
    def add(self, session):
        self.__setitem__(getattr(session, CUSTOM_OBJ_SESSION_ID_NAME), session)

    @validateParm
    def remove(self, session):
        self.__delitem__(getattr(session, CUSTOM_OBJ_SESSION_ID_NAME))
		


class MessageSender(threading.Thread):
    def __init__(self, mqueue):
        self.mqueue = mqueue
        threading.Thread.__init__(self)

    def run(self):
        logger.info("message sender started")
        while True:
            cmd = self.mqueue.get()
            logger.debug("find sender command : {}".format(cmd))
            def exec_cmd():
                cmd.pop("handle")(**cmd)
            executor = threading.Thread(target=exec_cmd)
            executor.daemon = True
            executor.start()
        

